#include <cmath>
#include <cstdio>
#include <queue>

using namespace std;
const int N = 1e5 + 5, M = N * 2;
struct E {
  int v, next;
} e[M];
int h[N];
// 以上 链表模板

int len, ans, lg,
    f[N][20],  // 倍增法预处理的cost数组
    dep[N],    // 用于bfs，兼具visited数组的功能
    d[N];
// 以上 倍增法求LCA子树的总权值
int n, m;
void add(int u, int v) {
  e[++len].v = v;
  e[len].next = h[u];
  h[u] = len;
}
void bfs(int start) {
  queue<int> q;
  dep[start] = 1;
  q.push(start);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int j = h[u]; j; j = e[j].next) {
      int v = e[j].v;
      if (dep[v]) continue;
      dep[v] = dep[u] + 1;
      q.push(v);
      f[v][0] = u;
      for (int k = 1; k <= lg; ++k) f[v][k] = f[f[v][k - 1]][k - 1];
    }
  }
}
// 求 x 与 y 的 lca
int lca(int x, int y) {
  // 令 x 比 y 深
  if (dep[y] > dep[x]) swap(x, y);
  // 令 y 和 x 在同一个深度
  for (int k = lg; k >= 0; --k) {
    if (dep[f[x][k]] >= dep[y]) x = f[x][k];
  }
  // 如果这个时候 y = x，那么 x，y 就都是它们自己的祖先。
  if (x == y) return x;
  // 不然的话，找到第一个不是它们祖先的两个点。
  for (int k = lg; k >= 0; --k) {
    if (f[x][k] != f[y][k]) x = f[x][k], y = f[y][k];
  }
  // 返回结果
  return f[x][0];
}

void dfs(int u, int fa) {
  for (int j = h[u]; j; j = e[j].next) {
    int v = e[j].v;
    if (v == fa) continue;
    dfs(v, u);
    // 这条边不在任何环中，去掉它就能分成两部分，这时候可以去掉m条额外边中任意一条
    if (d[v] == 0)
      ans += m;
    // 这条边e1在有且仅有一条额外边e2的环中，去掉e1和e2
    else if (d[v] == 1)
      ans += 1;
    // 没有其他可以增加d数组的方式了
    // 祖先的环数等于子节点环数之和
    d[u] += d[v];
  }
}

int main() {
  scanf("%d%d", &n, &m);
  lg = int(log(n) / log(2)) + 1;
  for (int i = 1; i < n; ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    add(u, v), add(v, u);
  }
  bfs(1);
  for (int i = 1; i <= m; ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    int LCA = lca(u, v);
    // 额外加一条路径构成一个环，让环上树边都+1
    // 显然全部+1不现实，采用树上差分方式
    d[LCA] -= 2, d[u] += 1, d[v] += 1;
  }
  dfs(1, 0);
  printf("%d\n", ans);
}
